/** 实现一个useRequest；要求有超时机制、重试机制、错误机制 */
function useRequest(requestFn, option = {}) {
    const {
        // 默认超时时间：5秒
        timeout = 5000,
        // 默认重试次数：3次
        retries = 3,
        // 错误回调
        onError  = (err) => {}
    } = option;

    // 一次请求（含超时控制）
    const fetchWithTimeout = (...args) => {
        return new Promise((resolve, reject) => {
            const timer = setTimeout(() => {
                reject(new Error('Request time out'))
            }, timeout);

            requestFn(...args)
                .then(res => {
                    clearTimeout(timer);
                    resolve(res);
                })
                .catch((err) => {
                    clearTimeout(timer);
                    reject(err);
                })
        })
    }

    // 主体请求逻辑
    const fetch = async(...args) => {
        let attempt = 0;
        while(attempt < retries) {
            try{
                const result = await fetchWithTimeout(...args);
                return result;
            }catch(error){
                attempt++;
                if(attempt >= retries){
                    onError(error);
                    throw error;
                }
            }
        }
    }

    return {fetch};
}

const mockApi = (msg) => {
    return new Promise((resolve, reject) =>{
        const delay = Math.random() * 1e3;
        setTimeout(() => {
            Math.random() > 0.5 ? resolve(`success:${msg}`) : reject('fail')
        }, delay);
    })
}

const {run} = useRequest(mockApi, {
    timeout: 2000,
    retries: 3,
    onError: (err) => console.log(err.message)
});

run('hello').then(value => console.log(value)).catch(error => console.log(error))